#include <stdlib.h>
#include <string.h>

#include "lib.h"
#include "rresource.h"
#include "rentry.h"

namespace Library
{

// warning C4200: nonstandard extension used : zero-sized array in struct/union
#pragma warning(disable:4200)
typedef struct _Resource
{
	pResourceEntry	owner;
	uint32			useCount;
	void *			userData;
	char			data[ 0 ];
} _Resource;


//----------------------------------------------------------------------------
// Public
//
bool8
Resource::release(void * resource)
{
	if (resource)
		return Resource::owner(resource)->release();

	return true;
}

String
Resource::name(void * resource)
{
	if (resource)
		return Resource::owner(resource)->name();

	return String::emptyString;
}

uint32
Resource::size(void * resource)
{
	if (resource)
		return Resource::owner(resource)->size();

	return 0;
}

uint32
Resource::useCount(void * resource)
{
	if (resource)
		return Resource::owner(resource)->useCount();

	return 0;
}

void *
Resource::userData(void * resource)
{
	if (resource)
		return Resource::owner(resource)->userData();
	
	return 0;
}

void
Resource::userData(void * resource, void * data)
{
	if (resource)
		Resource::owner(resource)->userData(data);
}

//----------------------------------------------------------------------------
// Protected
//
void *
Resource::allocate(pResourceEntry owner, uint32 size)
{
	if (owner)
	{
		_pResource ptr = (_pResource)malloc(sizeof(_Resource) + size);
		if (ptr)
		{
			memset(ptr, 0, sizeof(_Resource) + size);
			ptr->owner = owner;
		}
		return ptr->data;
	}
	
	return 0;
}

void
Resource::deallocate(void * resource)
{
	if (resource)
		free(Resource::head(resource));
}

//----------------------------------------------------------------------------
// Private
//
inline _pResource
Resource::head(void * resource)
{
	return ((_pResource)(((uint32)(resource)) - sizeof(_Resource)));
}

inline pResourceEntry
Resource::owner(void * resource)
{
	if (resource)
		return Resource::head(resource)->owner;

	return 0;
}

}; // namespace Library
